from asyncore import ExitNow
from MEMORY import *

class ecall:
    def __init__(self):
        self.a=[0]*8#8
    #更新该寄存器状态
    def update(self,a0:int,a1:int,a2:int,a3:int,a4:int,a5:int,a6:int,a7:int):
        self.a[0]=a0
        self.a[1]=a1
        self.a[2]=a2
        self.a[3]=a3
        self.a[4]=a4
        self.a[5]=a5
        self.a[6]=a6
        self.a[7]=a7


#获取当前文件状态
def lseek(fildes:int):
    if (fildes == 0) or (fildes == 1):
        return -29
    return -1

current_brk = 0x27000
code_end = 0

#自陷的返回跳出
def brk(addr):
    global current_brk
    if addr >= code_end:
        current_brk = addr
        return current_brk
    return -1
    #尝试修改brk

#自陷
def init(end):
    global code_end
    code_end=end
    return 0
    
#关闭
def close(fildes:int):
    if (fildes == 0) or (fildes == 1) or (fildes == 2):
        return 0
    return -1
  
#获取文件描述符状态并返回 
def fstat(fildes: int, buf, mem: Memory, mmu: MMU):
    stat_state=[]
    for offset in range(144):
        v_addr = buf+offset
        p_addr = mmu.Linear2Physical(v_addr,mem)
        stat_state.append(mem.Data8_port_out(p_addr))
    return stat_state
    
def read(fildes: int, buf, count, mem: Memory, mmu: MMU):
    if (fildes == 0) or (fildes == 2):
        broad = input().encode()
        broad += b'\0'
        size = min(count, len(broad))
        for offset in range(size):
            v_addr = buf+offset#虚拟地址
            p_addr = mmu.Linear2Physical(v_addr,mem)#物理地址
            mem.Data8_port_in(broad[offset],p_addr)#mem一字节输入
        return size
    
def write(fildes: int, buf, count, mem: Memory, mmu: MMU):
    out = ""
    cnt = 0
    #count = 多少字节
    for offset in range(count):
        v_addr = buf+offset#虚拟地址
        p_addr = mmu.Linear2Physical(v_addr,mem)#物理地址
        byte = mem.Data8_port_out(p_addr)#获取字节
        x = byte.to_bytes(1, "little").decode()#解码并加入x以便后面输出print
        out += x
        cnt += 1
    print(out, end='\n')
    return cnt


def sys_lseek(regs: ecall, mem: Memory, mmu: MMU):
    return lseek(regs.a[0])


def sys_brk(regs: ecall, mem: Memory, mmu: MMU):
    return brk(regs.a[0])


def sys_close(regs: ecall, mem: Memory, mmu: MMU):
    return close(regs.a[0])


def sys_fstat(regs: ecall, mem: Memory, mmu: MMU):
    return fstat(regs.a[0], regs.a[1], mem, mmu)


def sys_read(regs: ecall, mem: Memory, mmu: MMU):
    return read(regs.a[0], regs.a[1], regs.a[2], mem, mmu)


def sys_write(regs: ecall, mem: Memory, mmu: MMU):
   #  print("reg:",regs.a[4],regs.a[5])
    return write(regs.a[0], regs.a[5], regs.a[4] - regs.a[5], mem, mmu)


def sys_exit(regs: ecall, mem: Memory, mmu: MMU):
    print("Thread exit")
    print("Simulation Done!")
    exit()

sys_call_table = {57: sys_close, 62: sys_lseek, 63: sys_read, 4: sys_write, 80: sys_fstat, 93: sys_exit, 214: sys_brk}
call_0=ecall()

def sys_call_0(regs: ecall, mem: Memory, mmu: MMU):
    return sys_call_table[regs.a[7]](regs, mem, mmu)

def sys_call(a0:int,a1:int,a2:int,a3:int,a4:int,a5:int,a6:int,a7:int,mem: Memory, mmu: MMU):
    global call_0
    call_0.update(a0,a1,a2,a3,a4,a5,a6,a7)
    return sys_call_0(call_0,mem, mmu)
